home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / tpxms.zip / XMS.DOC < prev    next >
Text File  |  1993-01-04  |  28KB  |  635 lines

  1.  Page  1
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.                                T P X M S  v1.00
  19.  
  20.                         for Turbo Pascal v4.0 and above
  21.  
  22.                      Extended Memory Routines for HIMEM.SYS
  23.  
  24.                               Vernon E. Davis, Jr.
  25.  
  26.                                    07/30/89
  27.  Page 2
  28.  
  29.  
  30.  
  31.  
  32.  
  33.   Index  .................................................  Page  2
  34.   Introduction to the XMS Specification  .................  Page  3
  35.   Introduction to TPXMS.TPU  .............................  Page  4
  36.   Type Declarations in TPXMS.TPU
  37.      Bit32Struct  ........................................  Page  5
  38.      ExtMemMoveStruct  ...................................  Page  5
  39.      EMBHandleStruct  ....................................  Page  6
  40.      UMBSegmentStruct  ...................................  Page  6
  41.   Variable Declarations in TPXMS.TPU
  42.      isXMS  ..............................................  Page  7
  43.      XMSResult  ..........................................  Page  7
  44.      XMSError  ...........................................  Page  7
  45.      XMM_Control  ........................................  Page  7
  46.   High Memory Routines
  47.      Procedure GetMemHMA  ................................  Page  8
  48.      Procedure FreeMemHMA  ...............................  Page  8
  49.   Extended Memory Routines
  50.      Procedure QueryFreeMemXMS  ..........................  Page  9
  51.      Procedure QueryFreeBlockXMS  ........................  Page  9
  52.      Function  AllocExtMemBlockXMS  ......................  Page  9
  53.      Procedure FreeExtMemBlockXMS  .......................  Page  9
  54.      Procedure MoveExtMemBlockXMS  .......................  Page  9
  55.      Function  LockExtMemBlockXMS  .......................  Page 10
  56.      Procedure UnlockExtMemBlockXMS  .....................  Page 10
  57.      Procedure EMBHandleInfoXMS  .........................  Page 10
  58.      Procedure ReallocExtMemBlockXMS  ....................  Page 10
  59.   Upper Memory Routines
  60.      Procedure ReqUpperMemBlockUMB  ......................  Page 11
  61.      Procedure RelUpperMemBlockUMB  ......................  Page 11
  62.   Miscellaneous Routines
  63.      Function  XMSErrorMsg  ..............................  Page 12
  64.      Function  ExistXMS  .................................  Page 12
  65.      Procedure GetVerHiMem  ..............................  Page 12
  66.      Procedure GetRevHiMem  ..............................  Page 12
  67.      Procedure GlobalEnableA20  ..........................  Page 12
  68.      Procedure GlobalDisableA20  .........................  Page 12
  69.      Procedure LocalEnableA20  ...........................  Page 12
  70.      Procedure LocalDisableA20  ..........................  Page 12
  71.      Procedure QueryA20  .................................  Page 12
  72.  
  73.    Appendix A
  74.      Reading and Writing to the High Memory Area .........  Page 13
  75.    Appendix B
  76.      Reading and Writing with the Extended Memory Manager   Page 14
  77.    Appendix C
  78.      XMS Error Codes  ...................................   Page 15
  79.  
  80.  Page  3
  81.  
  82.   INTRODUCTION TO THE XMS SPECIFICATION:
  83.  
  84.      The XMS Specification, which is a Lotus/Intel/Microsoft/AST joint
  85.   venture, lays the groundwork for access to Extended Memory, the memory
  86.   above the 1-Megabyte boundary on AT-Class and above computer systems.
  87.   The heart of this is HIMEM.SYS; a device driver that loads at boot-time
  88.   from CONFIG.SYS and manages the complex task of reading from and writing
  89.   to Extended Memory.
  90.      This is not to be confused with the EMS Specification, which deals with
  91.   Expanded Memory on PC-Class and above computer systems. The EMS set of
  92.   rules govern a paging memory scheme that allow PC's to store large amounts
  93.   of data in EMS Memory without running out of DOS memory.
  94.      The routines of XMS allow access to Extended Memory for storing data
  95.   and, in some cases, actually running code; all from DOS. The problem of
  96.   switching from the Real Mode, which emulates the 8086/8088 processor, to
  97.   the Protected Mode, which allows access to the entire address space, and
  98.   back again is eliminated.
  99.      There are three classes of routines in XMS:
  100.      o  High Memory Area (HMA) routines:
  101.         These allow access to the first 64K of Extended Memory. Data can be
  102.         store here and code can be executed.
  103.      o  Extended Memory Management (XMM) routines:
  104.         These allow access to the entire physical address space of the
  105.         particular processor (80286 machines can access 16 Megabytes and
  106.         80386 machines can access 4 Gigabytes). Only data can be stored
  107.         and retrieved; no code can be executed.
  108.      o  Upper Memory Block (UMB) routines:
  109.         These allow access to the area of memory between 640K and 1-Megabyte.
  110.         Most AT-Class machines come with at least 1024K of RAM.
  111.         NOTE: The HIMEM.SYS version, as of this writing, does not implement
  112.         these routines and little is known how they will react. The Speci-
  113.         fication does spell out how to call the routines, but they will not
  114.         function.
  115.      There are also routines to manipulate the address line A20 for access
  116.   to the first 64K of Extended Memory and routines for determining the
  117.   version and revision number of HIMEM.SYS.
  118.      The XMS Specification, which includes HIMEM.SYS and documentation, can
  119.   be obtained through a computer club or from the Microsoft Systems Forum on
  120.   CompuServe. The Official XMS Specification can be obtained directly from
  121.   Microsoft.
  122.  
  123.  Page  4
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.   INTRODUCTION TO TPXMS.TPU
  135.  
  136.      The TPXMS.PAS source code is a Turbo Pascal v4.0 and above Unit that
  137.   utilizes the routines in HIMEM.SYS. When compiled, all the functions that
  138.   currently defined in the XMS Specification are easily accessable as Pascal
  139.   Procedures and Functions with Inline Machine Language calls to the XMM
  140.   Manager.
  141.  
  142.      Included in this package ( TPXMS.ZIP ):
  143.  
  144.      o  TPXMS.PAS   : the latest source code for TPXMS.TPU.
  145.      o  XMSTEST.PAS : the latest source code for the TPXMS.TPU tests.
  146.      o  TPXMS.DOC   : this documentation.
  147.  
  148.      Every effort has been taken to insure compatibility with both the
  149.   Specification and Turbo Pascal. As the Specification changes, so will
  150.   this package. Any comments about the XMS Specification should be directed
  151.   to Microsoft. Any comments concerning Turbo Pascal should be directed to
  152.   Borland International. Any comments concerning this package should be 
  153.   directed to the author:
  154.  
  155.         Vernon E. Davis, Jr.
  156.         17 Bowen Avenue
  157.         Woodstown, NJ 08098
  158.         CompuServe [71330,2705]
  159.  
  160.    I release this package to the Public Domain. All I am asking for is
  161.    recognition for the amount of time and work that went into creating
  162.    this package.
  163.                           Vernon E. Davis, Jr.   07/30/89
  164.                           
  165.  Page  5
  166.  
  167.    TYPE DECLARATIONS IN TPXMS.TPU
  168.  
  169. ** Bit32Struct = LongInt;
  170.  
  171.    This is just a reminder that any value stored in this type should be
  172.    treated as an UNSIGNED 32-bit value. Turbo Pascal's LongInt type is a
  173.    SIGNED 32-bit number; however, any constant value assigned to this type
  174.    is stored as an UNSIGNED number.
  175.    Example: 
  176.              Var lnum : LongInt;
  177.  
  178.              lnum := $FFFFFFFF;
  179.              Write(lnum);        ( the output displays -1 )
  180.  
  181.              However, the actual variable is stored as $FFFFFFFF
  182.  
  183.    The LongInt type has a range of -2,147,483,648 to +2,147,483,647. The
  184.    UNSIGNED number would be 4 Gigabytes or the actual address space of the
  185.    80386 processor. Very few people, if any, will need even 2 Gigabytes of
  186.    addressing, so this should not be a problem.
  187.  
  188. ** ExtMemMoveStruct =
  189.    Record
  190.       Length       : Bit32Struct;  Number of bytes to transfer.
  191.       SourceHandle : Word;         The Source Extended Memory Handle or 0.
  192.       SourceOffset : Bit32Struct;  The offset into block in which to start.
  193.       DestHandle   : Word;         The Dest. Extended Memory Handle or 0.
  194.       DestOffset   : Bit32Struct   The offset into block in which to start.
  195.    End;
  196.  
  197.    This structure sets up the movement of data from Conventional Memory to
  198.    Extended and visa-versa. According to the XMS Specifications, the move
  199.    can also occur from within Conventional Memory or Extended Memory. If
  200.    the SourceHandle or DestHandle is equal to zero, then it is considered
  201.    to be a Conventional Memory location, with the Segment:Offset pair placed
  202.    in the SourceOffset or DestOffset variable, respectively. The Extended
  203.    Memory Handle is obtained through the Allocate Function and the offset
  204.    is how far into the Extended Memory Block to start.
  205.    Example:
  206.              ExtMemMove : ExtMemMoveStruct;
  207.              XMSHandle  : Word;
  208.  
  209.              With ExtMemMove Do
  210.              Begin
  211.                 Length       :=      4000;  { move the entire video buffer }
  212.                 SourceHandle :=         0;  { Conventional Memory Handle   }
  213.                 SourceOffset := $B8000000;  { VIDEO = $B800:0000           }
  214.                 DestHandle   := XMSHandle;  { obtained via AllocExtMemXMS  }
  215.                 DestOffset   :=         0   { start at offset 0            }
  216.              End;
  217.  
  218.    When the MoveExtMemXMS Function is called, the contents of the video
  219.    screen would be written to Extended Memory. ( See the program XMSTEST.PAS
  220.    and Appendix B for actual code. )
  221.  
  222.  Page  6
  223.  
  224.    TYPE DECLARATIONS IN TPXMS.TPU ( continued )
  225.  
  226. ** EMBHandleStruct =
  227.    Record
  228.       LockCount   : Byte;  The number of times that the block has been locked.
  229.       FreeHandles : Byte;  The number of remaining Extended Memory Handles.
  230.       BlockLenKB  : Word   The length, in kilobytes, of the current Extended
  231.                            Memory Block. 
  232.    End;
  233.  
  234.    This structure is used by the EMBHandleInfoXMS procedure to extract
  235.    information about a particular Extended Memory Block.
  236.  
  237. ** UMBSegmentStruct =
  238.    Record
  239.       Segment   : Word;    The segment to which the Upper Memory Block has
  240.                            been assigned.
  241.       UMBSizePG : Word     The actual size of the Upper Memory Block in
  242.                            paragraphs (1 paragraph = 16 bytes).
  243.    End;
  244.  
  245.    Please note that this structure is defined, but the functions in the
  246.    current revision of HIMEM.SYS (2.06) does not access the Upper Memory
  247.    Block. All of these functions return $80 (Function not implemented).
  248.  
  249.  Page  7
  250.  
  251.    VARIABLE DECLARATIONS IN TPXMS.TPU
  252.  
  253. ** isXMS       : Boolean;              TRUE if HIMEM.SYS is correctly
  254.                                        installed. NOTE: All Procedures/
  255.                                        Functions in TPXMS.TPU check for isXMS
  256.                                        equal TRUE. If NOT TRUE, XMSResult
  257.                                        equals 0 and XMSError equals $80.
  258.  
  259. ** XMSResult   : Word;                 Equals 1 if the Function called is
  260.                                        successful, else 0. Some of these
  261.                                        functions do not use this as a result;
  262.                                        instead it is used to return a value 
  263.                                        from the Function.
  264.  
  265. ** XMSError    : Byte;                 If XMSResult = 0 and this byte is
  266.                                        greater or equal to $80, an error
  267.                                        has occurred. See the Appendix C
  268.                                        for an explanation of each value.
  269.  
  270. ** XMM_Control : Array[0..1] of Word;  This is the holder of the actual
  271.                                        address of the XMM_Control Function.
  272.                                        The Offset is contained in [0] and
  273.                                        the Segment is contained in [1]. This
  274.                                        is really an internal variable and has
  275.                                        no other use outside the XMS Functions.
  276.  Page  8
  277.  
  278.    HIGH MEMORY ROUTINES
  279.  
  280. ** Procedure GetMemHMA(Word);
  281.    This procedure attempts to allocate the High Memory Area with the Word
  282.    value passed. Check XMSResult = 1 for success. NOTE: If the /HMAMIN=
  283.    parameter is greater than the amount of memory requested, the procedure
  284.    will fail. ( See the XMS Specifications for more detail. ) NOTE: If
  285.    this procedure is called, the FreeMemHMA procedure MUST be called to
  286.    free the HMA before the program terminates or other programs cannot use
  287.    that memory. ( See Appendix A for reading and writing to the HMA. )
  288.  
  289. ** Procedure FreeMemHMA;
  290.    This procedure will attempt to release the High Memory Area. Check
  291.    XMSResult = 1 for success. NOTE: This function MUST be called to free
  292.    up the HMA before the program terminates or other programs will not 
  293.    have access to the memory.
  294.  
  295.  Page  9
  296.  
  297.    EXTENDED MEMORY ROUTINES
  298.  
  299.  
  300. ** Procedure QueryFreeMemXMS;
  301.    This procedure returns the TOTAL amount of free Extended Memory available
  302.    for access. The value is returned in XMSResult in kilobyte increments.
  303.    Example:
  304.  
  305.          QueryFreeMemXMS;
  306.          Write(XMSResult);
  307.          (The screen displays 256, which means there is a total of 256K
  308.           of Extended Memory available for access.)
  309.  
  310. ** Procedure QueryFreeBlockXMS;
  311.    This procedure returns the LARGEST BLOCK of Extended Memory available
  312.    for access. The value is returned in XMSResult in kilobyte increments.
  313.    Example:
  314.  
  315.          QueryFreeBlockXMS;
  316.          Write(XMSResult);
  317.          (The screen displays 64, which means the largest block of Extended
  318.           Memory available is 64K.)
  319.  
  320. ** Function  AllocExtMemBlockXMS(Word) : Word;
  321.    This function attempts to allocate a block of Extended Memory for data
  322.    storage. If XMSResult = 1 (success), then the value returned from the
  323.    function is the Extended Memory Handle to be used in reference to the
  324.    allocated block. The Word value passed to the function is the amount
  325.    of memory to allocate in kilobytes. Remember that the block must be
  326.    released before the program terminates or that block will remain in
  327.    memory and cannot be accessed again. If XMSResult = 0 (failure), do not
  328.    attempt to use the handle. ( See Appendix B for actual code. )
  329.  
  330. ** Procedure FreeExtMemBlockXMS(Word);
  331.    This procedure releases a block of Extended Memory that was previously
  332.    allocated. The Word value passed to the procedure is the Extended Memory
  333.    Handle of the allocated block. This procedure must be called to release
  334.    a previously allocated block before the program terminates or the memory
  335.    that the block resides in is lost. Check XMSResult = 1 for success.
  336.    ( See Appendix B for actual code. )
  337.  
  338. ** Procedure MoveExtMemBlockXMS(Var ExtMemMoveStruct);
  339.    This procedure moves data from Conventional Memory to Extended Memory and
  340.    visa-versa. The structure passed to the procedure contains the data
  341.    length and source/destination addresses. The structure type is defined
  342.    in the TPU Type Declarations. ( See the Type Declarations above. )
  343.    Check XMSResult = 1 for success. ( See Appendix B for actual code. )
  344.  
  345.  Page 10
  346.  
  347.    HIGH MEMORY ROUTINES ( continued )
  348.  
  349. ** Function  LockExtMemBlockXMS(Word) : Bit32Struct;
  350.    This function attempts to lock an allocated Extended Memory Block; that
  351.    is; making the block unmovable. If there are numerous unlocked blocks
  352.    in Extended Memory and one or more of those blocks are released, the XMM 
  353.    Manager moves the other blocks around to create one large free block of
  354.    memory. This function prevents the block in question from being moved
  355.    from its location in memory. The Word value passed is the Extended Memory
  356.    Handle of the allocated block. The Bit32Struct value returned is the
  357.    linear (actual) address of the block. Check XMSResult = 1 for success.
  358.  
  359.    * IMPORTANT *  A block can be locked more than once. The Lock Count,
  360.    which can be obtained with the EMBHandleInfoXMS procedure, is increased
  361.    by one each time the LockExtMemBlockXMS function is called, up to a 
  362.    maximum of 255 times. In order for a block to be released, its Lock Count
  363.    MUST be zero. Use the UnlockExtMemBlockXMS procedure to decrease the Lock
  364.    Count.
  365.  
  366. ** Procedure UnlockExtMemBlockXMS(Word);
  367.    This procedure reduces the Lock Count of a locked Extended Memory Block
  368.    by one. Because a block can be locked more than once, this routine must
  369.    be called until the Lock Count, obtained through the EMBHandleInfoXMS
  370.    procedure, is zero before the block can be released. The Word value
  371.    passed to the procedure is the Extended Memory Handle. Check XMSResult
  372.    = 1 for success.
  373.  
  374. ** Procedure EMBHandleInfoXMS(Word; Var EMBHandleStruct);
  375.    This procedure gathers information about a particular Extended Memory
  376.    Block and about the XMM environment. The Word value passed to the
  377.    procedure is the Extended Memory Handle. The structure passed to the
  378.    procedure will contain the following information after returning from
  379.    the call:
  380.  
  381.       o  The Lock Count: the number of times that this block has been
  382.          locked via the LockExtMemBlockXMS procedure. If this value is
  383.          zero then the block can be successfully released with the
  384.          FreeExtMemBlockXMS procedure.
  385.       o  The Free Handle Count: the number of free Extended Memory Handles
  386.          that are available. If HIMEM.SYS was loaded without the /NUMHANDLES=
  387.          parameter, then there are a total of 32 handles available.
  388.       o  The Block Size: this value, in kilobytes, is the current size of
  389.          the block in question.
  390.  
  391.    Check XMSResult = 1 for success.
  392.  
  393. ** Procedure ReallocExtMemBlockXMS(Word; Word);
  394.    This procedure will attempt to change the current size of the particular
  395.    Extended Memory Block. The first Word value passed to the procedure is
  396.    the Extended Memory Handle. The second Word value passed to the procedure
  397.    is the new size, in kilobytes, of the block.
  398.  
  399.    * NOTE *  As of this writing, this procedure is not functional. It is a
  400.    result of HIMEM.SYS, not the source code. If called, XMSResult will
  401.    contain 0 and the value in XMSError will be $80 (Function not implemented).
  402.    When HIMEM.SYS is updated, this procedure should work as planned and
  403.    the TPXMS.TPU need not be recompiled.
  404.  
  405.  Page 11
  406.  
  407.    UPPER MEMORY ROUTINES
  408.  
  409. ** Procedure ReqUpperMemBlockUMB(Word; Var UMBSegmentStruct);
  410.    This procedure attempts to allocate an Upper Memory Block. The Word value
  411.    passed to the procedure is the amount of memory to allocate in paragraphs
  412.    ( 1 paragraph = 16 bytes ). The structure passed to the procedure will
  413.    contain the following information after returning from the call:
  414.  
  415.       o  The Segment : the segment of the UMB.
  416.       o  The Block Size : the actual size of the UMB in paragraphs.
  417.  
  418.    * NOTE *  As of this writing, this procedure is not functional. It is a
  419.    result of HIMEM.SYS, not the source code. If called, XMSResult will
  420.    contain 0 and the value in XMSError will be $80 (Function not implemented).
  421.    When HIMEM.SYS is updated, this procedure should work as planned and
  422.    the TPXMS.TPU need not be recompiled.
  423.  
  424. ** Procedure RelUpperMemBlockUMB(Word);
  425.    This procedure releases a previously allocated Upper Memory Block. The
  426.    Word value passed to the procedure is the Segment of the UMB.
  427.  
  428.    * NOTE *  As of this writing, this procedure is not functional. It is a
  429.    result of HIMEM.SYS, not the source code. If called, XMSResult will
  430.    contain 0 and the value in XMSError will be $80 (Function not implemented).
  431.    When HIMEM.SYS is updated, this procedure should work as planned and
  432.    the TPXMS.TPU need not be recompiled.
  433.  
  434.  Page 12
  435.  
  436.    MISCELLANEOUS ROUTINES
  437.  
  438. ** Function  XMSErrorMsg : String;
  439.    This function is not part of the XMS Specification, but is provided as
  440.    convienence to the programmer in intrepreting Error Codes returned by
  441.    the XMM_Control Function. A text message is returned based on the value
  442.    in the XMSError byte. Example: If XMSResult = 0 Then Writeln(XMSErrorMsg);
  443.  
  444. ** Function  ExistXMS : Boolean;
  445.    This Function is called once in the TPU and really does not need to be
  446.    called again. It sets the variable isXMS TRUE if HIMEM.SYS is properly
  447.    loaded and loads the XMM_Control array with the address of XMM_Control.
  448.  
  449. ** Procedure GetVerHiMem;
  450.    This procedure retrieves the version number of HIMEM.SYS in XMSResult.
  451.  
  452. ** Procedure GetRevHiMem;
  453.    This procedure retrieves the revision number of HIMEM.SYS in XMSResult.
  454.  
  455. ** Procedure GlobalEnableA20;
  456.    This toggles the address line A20 high so that access to the High Memory
  457.    Area is obtained. THIS PROCEDURE MUST BE CALLED to access the HMA or
  458.    the system will hang when trying to write to it. ( See Appendix A for
  459.    actual code. )  The GlobalDisableA20 procedure MUST be called BEFORE
  460.    releasing the HMA and BEFORE the program terminates. Check XMSResult = 1
  461.    for success.
  462.  
  463. ** Procedure GlobalDisableA20;
  464.    This toggles the address line A20 low. This procedure MUST be called 
  465.    BEFORE releasing the HMA and BEFORE the program terminates. Check
  466.    XMSResult = 1 for success.
  467.  
  468. ** Procedure LocalEnableA20;
  469.    This toggles the address line A20 high so that access to the first 64K
  470.    of Extended Memory is obtained. THIS PROCEDURE MUST BE CALLED to access
  471.    the memory or the system will hang when trying to write to it. ( See
  472.    Appendix A for actual code. )  The LocalDisableA20 procedure MUST be
  473.    called BEFORE the program terminates. Check XMSResult = 1 for success.
  474.  
  475.    * IMPORTANT * This procedure allows the bypass of the HMA access routines.
  476.    Therefore, if there is another program, such as a TSR, in the HMA area,
  477.    and Extended Memory is directly written to, that program in the HMA could
  478.    be destroyed. One possible way to check if the HMA is in use would be to
  479.    call the QueryA20 procedure to determine if address line A20 is active.
  480.    Another way would be to attempt to allocate the HMA by calling the
  481.    GetMemHMA procedure. In short, use the LocalEnableA20 procedure at the
  482.    risk of hanging the system.
  483.  
  484. ** Procedure LocalDisableA20;
  485.    This toggles the address line A20 low. This procedure MUST be called 
  486.    BEFORE the program terminates. Check XMSResult = 1 for success.
  487.  
  488. ** Procedure QueryA20;
  489.    This procedure determines the status of address line A20.
  490.    If XMSResult = 1 then A20 is active (enabled).
  491.    If XMSResult = 0 then A20 is inactive (disabled).
  492.  
  493.  Page 13
  494.  
  495. Appendix A - Reading and Writing to the High Memory Area ( HMA )
  496.  
  497.    The HMA can be directly accessed by DOS and Turbo Pascal. The address of
  498.    the HMA officially begins at $FFFF:$0010 and ends at $FFFF:$FFFF, giving
  499.    a total memory capacity of 65520 bytes ( 64K - 16 bytes ). Study the
  500.    following piece of code:
  501.  
  502.    Program HMA_R_W;
  503.    (* 
  504.    NOTE: This program assumes that HIMEM.SYS is properly loaded and that
  505.    there is 64Kbytes free in the HMA area.
  506.    *)
  507.    Uses
  508.       CRT,DOS,TPXMS;
  509.    Var
  510.       vid : Byte Absolute $B800:$0000;
  511.       hma : Byte Absolute $FFFF:$0010;
  512.       i   : Integer;
  513.    Begin
  514.       GetMemHMA($FFFF);          { Reserve all of the HMA }
  515.       GlobalEnableA20;           { Toggle the A20 address line high }
  516.       ClrScr;                    { Clear the screen }
  517.       For i := 1 To 1999 Do
  518.          Write('A');             { Fill the screen with "A" }
  519.       Move(vid,hma,4000);        { Copy the contents of the screen to HMA }
  520.       ClrScr;                    { Clear the screen }
  521.       Move(hma,vid,4000);        { Restore the screen from HMA }
  522.       GlobalDisableA20;          { Toggle the A20 address line low }
  523.       FreeMemHMA                 { Release the HMA }
  524.    End.
  525.  
  526.  
  527.    The HMA can be bypassed by reading and writing to Direct Memory in the
  528.    same fashion using the LocalEnable/DisableA20 procedures. However, any
  529.    program, such as a TSR currently running in the HMA area, could be over-
  530.    written. Use of this method is not recommended unless it is an absolute
  531.    certainty that there is nothing in the HMA.
  532.  
  533.    Program DMA_R_W;
  534.    (*
  535.    NOTE: This program assumes that HIMEM.SYS is properly loaded.
  536.    *)
  537.    Uses
  538.       CRT,DOS,TPXMS;
  539.    Var
  540.       vid : Byte Absolute $B800:$0000;
  541.       dma : Byte Absolute $FFFF:$0010;
  542.       i   : Integer;
  543.    Begin
  544.       LocalEnableA20;            { Toggle the A20 address line high }
  545.       ClrScr;                    { Clear the screen }
  546.       For i := 1 To 1999 Do
  547.          Write('A');             { Fill the screen with "A" }
  548.       Move(vid,dma,4000);        { Copy the contents of the screen to HMA }
  549.       ClrScr;                    { Clear the screen }
  550.       Move(dma,vid,4000);        { Restore the screen from HMA }
  551.       LocalDisableA20            { Toggle the A20 address line low }
  552.    End.
  553.  
  554.  Page 14
  555.  
  556. Appendix B - Reading and Writing with the Extended Memory Manager ( XMM )
  557.  
  558.    The XMM routines provide access to Extended Memory that is transparent
  559.    to the programmer in switching from Real Mode to Protected Mode and back
  560.    again. Study the following piece of code:
  561.  
  562.    Program XMM_R_W;
  563.    (* 
  564.    NOTE: This program assumes that HIMEM.SYS is properly loaded and that
  565.    there is 4Kbytes free in Extended Memory.
  566.    *)
  567.    Uses
  568.       CRT,DOS,TPXMS;
  569.    Var
  570.       XMSHandle   : Word;
  571.       ExtMemMove  : ExtMemMoveStruct;
  572.       i           : Integer;
  573.    Begin
  574.       XMSHandle := AllocExtMemBlockXMS(4);  { Allocate 4 kilobytes }
  575.       With ExtMemMove Do                    { Load the structure }
  576.       Begin
  577.          Length       :=      4000;         { Size of video screen }
  578.          SourceHandle :=         0;         { Use Conventional Memory }
  579.          SourceOffset := $B8000000;         { VIDEO = $B800:$0000 }
  580.          DestHandle   := XMSHandle;         { Extended Memory Handle }
  581.          DestOffset   :=         0          { Offset 0 into the block }
  582.       End;
  583.       ClrScr;                               { Clear the screen }
  584.       For i := 1 To 1999 Do Write('A');     { Fill the screen with "A" }
  585.       MoveExtMemBlockXMS(ExtMemMove);       { Move screen to Ext. Memory }
  586.       ClrScr;                               { Clear the screen }
  587.       With ExtMemMove Do                    { Load the structure }
  588.       Begin
  589.          Length       :=      4000;         { Size of video screen }
  590.          SourceHandle := XMSHandle;         { Extended Memory Handle }
  591.          SourceOffset :=         0;         { Offset 0 into the block }
  592.          DestHandle   :=         0;         { Use Conventional Memory }
  593.          DestOffset   := $B8000000          { VIDEO = $B800:$0000 }
  594.       End;
  595.       MoveExtMemBlockXMS(ExtMemMove);       { Restore screen from Ext. Mem. }
  596.       FreeExtMemBlockXMS(XMSHandle)         { Release Extended Memory Block }
  597.    End.
  598.  
  599.  Page 15
  600.  
  601. Appendix C - XMS ERROR CODES
  602.  
  603.    If XMSResult = 0 and XMSError is greater than or equal to $80 then
  604.    an error has occurred. The following codes are valid as of this
  605.    writing:
  606.  
  607.    $80 : XMS Function not implemented
  608.    $81 : VDISK detected
  609.    $82 : A20 Error
  610.    $8E : General Driver Error
  611.    $8F : Unrecoverable Driver Error
  612.    $90 : HMA does not exist
  613.    $91 : HMA in use by another process
  614.    $92 : Memory requested less than /HMAMIN= parameter
  615.    $93 : HMA not allocated
  616.    $94 : A20 is enabled
  617.    $A0 : All of Extended Memory is allocated
  618.    $A1 : No Extended Memory Handles available
  619.    $A2 : Extended Memory Handle is invalid
  620.    $A3 : Extended Move Structure: Source Handle is invalid
  621.    $A4 : Extended Move Structure: Source Offset is invalid
  622.    $A5 : Extended Move Structure: Destination Handle is invalid
  623.    $A6 : Extended Move Structure: Destination Offset is invalid
  624.    $A7 : Extended Move Structure: Length is invalid
  625.    $A8 : Extended Move Structure: Move has invalid overlap
  626.    $A9 : Parity Error
  627.    $AA : Block is not locked
  628.    $AB : Block is locked
  629.    $AC : Block Lock Count has overflowed
  630.    $AD : Block Lock has failed
  631.    $B0 : A smaller Upper Memory Block is available
  632.    $B1 : No Upper Memory Blocks are available
  633.    $B2 : Upper Memory Block Segment Number is invalid
  634.  
  635.